package com.ant.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.SneakyThrows;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;

/**
 * 自定义Map
 *
 * @author LB
 */
@Component
public class FastMap extends LinkedHashMap<String, Object> implements Comparator<FastMap>, Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 构造方法
     */
    public FastMap() {

    }

    /**
     * 获取对应Key的Stirng值
     *
     * @param key
     * @return
     */
    public String getString(String key) {
        Object obj = get(key);
        return obj == null ? "" : obj.toString().trim();
    }


    public String getJsonString(String key) {
        Object obj = get(key);
        if (obj == null) {
            return "";
        } else {
            return JSON.toJSONString(obj);
        }
    }

    /**
     * 获取对应Key的Integer值
     *
     * @param key
     * @return
     */
    public int getInt(String key) {
        Object o = get(key);
        if (o != null && !StringUtils.isEmpty(o)) {
            if (o instanceof Number) {
                return ((Number) o).intValue();
            } else {
                return (int) getDouble(key);
            }
        } else {
            return 0;
        }
    }

    /**
     * 获取状态
     *
     * @param key
     * @return
     */
    public int getStatus(String key) {
        Object o = get(key);
        if (o != null && !StringUtils.isEmpty(o)) {
            if (o instanceof Number) {
                return ((Number) o).intValue();
            } else {
                return (int) getDouble(key);
            }
        } else {
            return -1;
        }
    }

    /**
     * 获取对应Key的Double值
     *
     * @param key
     * @return
     */
    public double getDouble(String key) {
        Object o = get(key);
        String msg = "fastMap[" + key + "] is not a number. value = [" + o + "]";
        if (o != null) {
            try {
                if (o instanceof Number) {
                    return ((Number) o).doubleValue();
                } else {
                    return Double.parseDouble((String) o);
                }
            } catch (Exception e) {
                //throw new NestableRuntimeException(msg);
                return 0;
            }
        } else {
            return 0;
        }
    }

    public long getLong(String key) {
        Object o = get(key);
        String msg = "fastMap[" + key + "] is not a long. value = [" + o + "]";
        if (o != null) {
            return (long) getDouble(key);
        } else {
            return 0;
        }
    }

    /**
     * 获取对应Key的boolean值
     *
     * @param key
     * @return
     */
    public boolean getBoolean(String key) {
        Object obj = get(key);
        return obj != null && Boolean.parseBoolean(obj.toString());
    }

    /**
     * 通过json转化为fastMap
     *
     * @param objString
     * @return
     */
    public static FastMap fromObject(String objString) {
        if (StringUtils.isEmpty(objString)) {
            return new FastMap();
        } else {
            return JSONObject.parseObject(objString, FastMap.class);
        }
    }

    /**
     * 将object转化为fastMap
     *
     * @param o
     * @return
     */
    public static FastMap fromObject(Object o) {
        if (o == null) {
            return new FastMap();
        } else {
            return JSONObject.parseObject(JSON.toJSONString(o), FastMap.class);
        }
    }

    /**
     * 通过key获取fastMap
     *
     * @param key
     * @return
     */
    public FastMap getFastMap(String key) {
        Object o = get(key);
        if (StringUtils.isEmpty(key)) {
            return new FastMap();
        } else if (o == null) {
            return new FastMap();
        }
        String type = o.getClass().getName();
        if (this.getClass().getName().equals(type)) {
            return (FastMap) o;
        } else if (String.class.getName().equals(type)) {
            return fromObject(JSON.toJSONString(o));
        } else {
            return fromObject(JSON.toJSONString(o));
        }
    }

    /**
     * 通过key获取List
     *
     * @param key
     * @return
     */
    public List<FastMap> getList(String key) {
        try {
            Object o = get(key);
            if (o == null) {
                return new ArrayList<FastMap>();
            }

            //先转化一下o，可能传入的是=，不是:
            String oString = JSON.toJSONString(o, SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames);
            return JSONObject.parseArray(oString, FastMap.class);
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<FastMap>();
        }
    }

    /**
     * 将fastMap转化为String
     */
    @Override
    public String toString() {
        return JSON.toJSONString(this, SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames);
    }

    /**
     * 克隆，效率低但是安全
     */
    @Override
    public FastMap clone() {
        FastMap map = new FastMap();
        for (Entry<String, Object> entry : this.entrySet()) {
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }

    @Override
    public int compare(FastMap o1, FastMap o2) {
        return new Integer(o1.getClass().getName()).compareTo(new Integer(o2.getClass().getName()));
    }

    /**
     * 检查值是否存在
     */
    public boolean contains(Object value) {
        return super.containsValue(value);
    }

    /**
     * 检查键是否存在
     *
     * @param key
     * @return
     */
    public boolean containsKey(String key) {
        return super.containsKey(key);
    }

    /**
     * 将Map里的key下划线转小驼峰
     *
     * @return
     */
    public FastMap underlineToCamel() {
        FastMap map = new FastMap();
        for (Entry<String, Object> entry : this.entrySet()) {
            map.put(underlineToCamel(entry.getKey()), entry.getValue());
        }
        return map;
    }

    /**
     * 将Map里的key小驼峰转下划线
     *
     * @param isUpper：true：统一都转大写；false-统一转小写
     * @return
     */
    public FastMap camelToUnderline(boolean isUpper) {
        FastMap map = new FastMap();
        for (Entry<String, Object> entry : this.entrySet()) {
            map.put(camelToUnderline(entry.getKey(), isUpper), entry.getValue());
        }
        return map;
    }

    /**
     * 获取map里所有的key(重点注意所有的key都加了单引号)
     *
     * @param link 连接符，一般是逗号
     * @return
     */
    public String getKeys(String link) {
        String keys = "";
        for (Entry<String, Object> entry : this.entrySet()) {
            keys = keys + "'" + entry.getKey() + "'" + link;
        }

        //去掉最后一个逗号
        keys = keys.substring(0, keys.length() - 1);
        return keys;
    }

    /**
     * 重写put方法，默认转化小驼峰命名
     *
     * @param key
     * @param value
     */
	/*@Override
	public Object put(String key, Object value){
		return this.put(key, value, true);
	}*/


    /**
     * 重写put方法，转化小驼峰命名
     * @param key
     * @param value
     * @param toCamel：true:将key转化为小驼峰，false:不转化
     * @return
     */
	/*public Object put(String key, Object value, boolean toCamel){
		String newKey;
		if (toCamel){
			newKey = underlineToCamel(key);	
		}else {
			newKey = key;
		}
		
		if (this.containsKey(newKey)&&this.containsValue(value)){
			return null;
		}
		
		if (value==null){
			value = "";
		}
		
		return super.put(newKey, value);
	}*/

    /**
     * 下划线转小驼峰
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        char UNDERLINE = '_';

        if (param == null || StringUtils.isEmpty(param.trim())) {
            return "";
        }

        int len = param.length();

        //不包含下划线的，需要检查并转化为小写
        if (!param.contains("_")) {
            boolean isUpper = false;
            boolean isLow = false;
            for (int i = 0; i < len; i++) {
                char c = param.charAt(i);
                if (Character.isLowerCase(c)) {
                    isLow = true; //检查到小写
                } else if (Character.isUpperCase(c)) {
                    isUpper = true; //检查到大写
                } else if (Character.isDigit(c)) {
                    isLow = true; //检查到数字就是小写
                }
            }

            //全部是大写的，需要转化为小写
            if (isUpper && !isLow) {
                return param.toLowerCase();
            } else {
                //有大写，有小写，直接返回原值
                return param;
            }
        }

        StringBuilder sb = new StringBuilder(len);
        boolean flag = false; // "_" 后转大写标志,默认字符前面没有"_"
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                flag = true;
                continue;   //标志设置为true,跳过
            } else {
                if (flag) {
                    //表示当前字符前面是"_" ,当前字符转大写
                    sb.append(Character.toUpperCase(param.charAt(i)));
                    flag = false;  //重置标识
                } else {
                    sb.append(Character.toLowerCase(param.charAt(i)));
                }
            }
        }
        return sb.toString();
    }

    /**
     * 小驼峰转下划线
     *
     * @param param
     * @param toUpper： true：统一都转大写；false-统一转小写
     * @return
     */
    public static String camelToUnderline(String param, boolean toUpper) {
        char UNDERLINE = '_';

        if (param == null || StringUtils.isEmpty(param.trim())) {
            return "";
        }

        int len = param.length();

        //已经包含下划线的，返回原值
        if (param.contains("_")) {
            return param;
        }

        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
            }
            if (toUpper) {
                sb.append(Character.toUpperCase(c));  //统一都转大写
            } else {
                sb.append(Character.toLowerCase(c));  //统一都转小写
            }
        }
        return sb.toString();
    }

    /**
     * 将bean转化为map
     *
     * @param bean
     * @return
     */
    public static <T> FastMap beanToMap(T bean) {
        FastMap fastMap = new FastMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                Object o = beanMap.get(key);
                //ConcurrentHashMap 不能put null 的原因是因为：无法分辨是key没找到的null还是有key值为null值，
                //而这在多线程里面是模糊不清的，所以压根就不让put null。
                if (key != null) {
					/*if (o==null){
						logger.error(key+" value is null. ");
						o = "";
					}*/
                    fastMap.put(key + "", o);
                }
            }
        }
        return fastMap;
    }

    public int getPageIndex() {
        Object o = get("page");
        if (o == null || StringUtils.isEmpty(o)) {
            return 1; //默认第一页
        } else {
            return this.getInt("page");
        }
    }

    public int getPageSize() {
        Object o = get("limit");
        if (o == null || StringUtils.isEmpty(o)) {
            return 10; //默认10行
        } else {
            return this.getInt("limit");
        }
    }

    /**
     * 获取 List<List<Object>>，用于excel解析
     *
     * @param key
     * @return
     */
    public List<List<Object>> get2ListObject(String key) {
        Object o = get(key);
        if (Objects.isNull(o)) {
            return new ArrayList<>();
        }
        return (List<List<Object>>) o;
    }

    /**
     * 获取 List<String>，用于excel解析
     *
     * @param key
     * @return
     */
    public List<String> getListString(String key) {
        Object o = get(key);
        if (Objects.isNull(o)) {
            return new ArrayList<>();
        }
        return (List<String>) o;
    }

    /**
     * 获取 List<Integer>，用于excel解析
     *
     * @param key
     * @return
     */
    public List<Integer> getListInteger(String key) {
        Object o = get(key);
        if (Objects.isNull(o)) {
            return new ArrayList<>();
        }
        return (List<Integer>) o;
    }

    /**
     * 将map转化为Bean
     */
    @SneakyThrows
    public static void mapToBean(FastMap map, Object o) {
        DateTimeConverter dtConverter = new DateTimeConverter();
        ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean();
        convertUtilsBean.deregister(Date.class);
        convertUtilsBean.register(dtConverter, Date.class);
        BeanUtilsBean beanUtilsBean = new BeanUtilsBean(convertUtilsBean, new PropertyUtilsBean());
        beanUtilsBean.populate(o, map);
    }

    public static Map<String, Object> fastMapToMap(FastMap source) {
        Map<String, Object> result = new HashMap<>();
        for (Entry<String, Object> entry : source.entrySet()) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    public static FastMap mapToFastMap(Map<String, Object> source) {
        FastMap result = new FastMap();
        for (Entry<String, Object> entry : source.entrySet()) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

}
